/*
 * block_matrix_helper.c
 *
 *  Created on: Dec 1, 2011
 *      Author: bendischinger
 */

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#include "block_matrix.h"
#include "block_cache.h"
#include "helper_thread.h"
#include "test_stat.h"


void
read_block_helper(block_matrix_t *mat, int *block, int i, int j) {
	off_t offset = BLOCK_FD_OFFSET(mat, i, j);
	test_time_t start = start_timer();
	int error = EAGAIN;
	int use_cache = mat->flags & M_PREFETCH;

	if (use_cache && is_cached_block(&mat->blk_cache, offset)) {
		return;
	}

	if (use_cache && (mat->flags & M_AIO)) {
		error = put_aio_cached_block(&mat->blk_cache, offset);
		if (error == EAGAIN) {
			global_stat.aio_eagain++;
		}
	}

	if (error == EAGAIN) {
		/* error case */
		lseek(mat->fd, offset, SEEK_SET);
		read(mat->fd, block, mat->blk_size);
		if (use_cache) {
			put_cached_block(&mat->blk_cache, offset, block);
		}
	}

	global_stat.helper_read_time += stop_timer(start, UNIT_USEC);
	global_stat.helper_read_cnt++;
}


void
add_matrix_helper(block_matrix_t **mat) {
	block_matrix_t *left = mat[0];
	block_matrix_t *right = mat[1];
//	block_matrix_t *out = args[2];
	int i,j;
	int *block_left = malloc(left->blk_size);
	int *block_right = malloc(left->blk_size);
//	int *block_out = malloc(left->blk_size);
	for (i=0;i<left->blk_rows;i++) {
		for (j=0;j<left->blk_cols;j++) {
//			bzero(block_out, left->blk_size);
			HELPER_SYNC();
			read_block_helper(left, block_left, i, j);
			read_block_helper(right, block_right, i, j);
//			add_block(out, block_left, block_right, block_out);
//			write_block(out, block_out, i, j);
		}
	}
	free(block_left);
	free(block_right);
//	free(block_out);
}


void
multiply_matrix_helper(block_matrix_t **mat) {
	block_matrix_t *left = mat[0];
	block_matrix_t *right = mat[1];
//	block_matrix_t *out = args[2];
	int i,j,k;
	int *block_left = malloc(left->blk_size);
	int *block_right = malloc(left->blk_size);
//	int *block_out = malloc(left->blk_size);
	for (i=0;i<left->blk_rows;i++) {
		for (j=0;j<left->blk_cols;j++) {
//			bzero(block_out, left->blk_size);
			for (k=0;k<left->blk_rows;k++) { /* We're assuming square matrix */
				HELPER_SYNC();
				read_block_helper(left, block_left, i, k);
				read_block_helper(right, block_right, k, j);
//				multiply_block(out, block_left, block_right, block_out);
			}
//			write_block(out, block_out, i, j);
		}
	}
	free(block_left);
	free(block_right);
//	free(block_out);
}
